package com.naiterui.ehp.bs.patient.handler;

import cn.hutool.json.JSONUtil;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.ehp.bp.bo.im.PatientMsgSendParamBO;
import com.naiterui.ehp.bp.bo.patient.MsgPublishMpParamBO;
import com.naiterui.ehp.bp.constants.CommonConstant;
import com.naiterui.ehp.bp.utils.date.DateUtil;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bs.patient.bo.notice.MedicalRecordMsg;
import com.naiterui.ehp.bs.patient.bo.notice.OutlineMsg;
import com.naiterui.ehp.bs.patient.bo.notice.subscribe.ConsultReplySubscribe;
import com.naiterui.ehp.bs.patient.bo.notice.subscribe.MedicalSubscribe;
import com.naiterui.ehp.bs.patient.bo.notice.subscribe.ReminderSubscribe;
import com.naiterui.ehp.bs.patient.constants.PatientJumperEnum;
import com.naiterui.ehp.bs.patient.handler.data.PublishMsgData;
import com.naiterui.ehp.bs.patient.handler.data.PublishMsgEvent;
import com.naiterui.ehp.bs.patient.service.ISubscribeNoticeService;
import com.naiterui.ehp.bs.patient.service.ITemplateNoticeService;
import com.naiterui.ehp.bs.wechat.param.custom.*;
import com.naiterui.ehp.bs.wechat.protocol.msg.subscribe.SubscribeMp;
import com.naiterui.ehp.bs.wechat.service.ICustomMsgApiService;
import com.naiterui.ehp.bs.wechat.service.IMediaApiService;
import com.naiterui.ehp.bs.wechat.service.impl.MediaApiServiceImpl;
import com.naiterui.ehp.bs.wechat.service.impl.WebAuthorizeApiServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * 微信用户
 * 被动消息接收事件处理
 * （客服消息、模板消息）
 *
 * @author gaoliangliang
 * @date 2019-07-12 14:27
 * @since 1.0.0
 */
@Component
@AllArgsConstructor
public class PublishMsgHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(PublishMsgHandler.class);

    private final ICustomMsgApiService customMsgApiService;
    private final ITemplateNoticeService templateNoticeService;
    private final IMediaApiService mediaApiService;
    private final WebAuthorizeApiServiceImpl webAuthorizeApiServiceImpl;
    private final ISubscribeNoticeService subscribeNoticeService;

    /**
     * 文本消息
     *
     * @param publishMsgEvent
     */
    @Async
    @EventListener(classes = PublishMsgEvent.class, condition = "#root.args[0].msgType == " + PatientMsgSendParamBO.MsgType.TEXT)
    public void publishMsg4Text(PublishMsgEvent publishMsgEvent) {
        LOGGER.debug("文本消息");

        PublishMsgData msgData = publishMsgEvent.getEventData();
        BaseCustomParam customMsgParam = new TextMsgParam(msgData.getOpenId(), msgData.getDoctorName() + "医生：" + msgData.getContent());
        String msgView = msgData.getContent();

        this.doPublish(msgData, customMsgParam, msgView, null);

    }

    /**
     * 多媒体消息（图片、音频、视频、小视频）
     *
     * @param publishMsgEvent
     */
    @Async
    @EventListener(classes = PublishMsgEvent.class,
            condition = "#root.args[0].msgType == " + PatientMsgSendParamBO.MsgType.IMAGE +
                    " || #root.args[0].msgType == " + PatientMsgSendParamBO.MsgType.VOICE +
                    " || #root.args[0].msgType == " + PatientMsgSendParamBO.MsgType.VIDEO +
                    " || #root.args[0].msgType == " + PatientMsgSendParamBO.MsgType.SHORTVIDEO)
    public void publishMsg4Nomal(PublishMsgEvent publishMsgEvent) {

        PublishMsgData msgData = publishMsgEvent.getEventData();
        String mediaId;
        BaseCustomParam customMsgParam;
        String msgView;
        String msgSimple;

        switch (publishMsgEvent.getMsgType()) {
            case PatientMsgSendParamBO.MsgType.IMAGE:
                mediaId = mediaApiService.uploadTempMedia(MediaApiServiceImpl.MEDIA_TYPE_IMAGE, msgData.getContent().replaceAll(ConfigUtil.getString("im.image.domain"), ConfigUtil.getString("im.image.root")));
                customMsgParam = new ImageMsgParam(msgData.getOpenId(), mediaId);
                msgView = "【图片】";
                msgSimple = msgData.getDoctorName() + "医生给您发送了一张图片";
                break;
            case PatientMsgSendParamBO.MsgType.VOICE:
                mediaId = mediaApiService.uploadTempMedia(MediaApiServiceImpl.MEDIA_TYPE_VOICE, msgData.getContent().replaceAll(ConfigUtil.getString("im.radio.domain"), ConfigUtil.getString("im.radio.root")));
                customMsgParam = new VoiceMsgParam(msgData.getOpenId(), mediaId);
                msgView = "【语音】";
                msgSimple = msgData.getDoctorName() + "医生给您发送了一条语音";
                break;
            case PatientMsgSendParamBO.MsgType.VIDEO:
            case PatientMsgSendParamBO.MsgType.SHORTVIDEO:
                mediaId = mediaApiService.uploadTempMedia(MediaApiServiceImpl.MEDIA_TYPE_IMAGE, msgData.getContent().replaceAll(ConfigUtil.getString("im.video.domain"), ConfigUtil.getString("im.video.root")));
                customMsgParam = new VideoMsgParam(msgData.getOpenId(), mediaId, "");
                msgView = "【视频】";
                msgSimple = msgData.getDoctorName() + "医生给您发送了一份视频";
                break;
            default:
                return;
        }

        this.doPublish(msgData, customMsgParam, msgView, msgSimple);
    }

    /**
     * 处方消息
     *
     * @param publishMsgEvent
     */
    @Async
    @EventListener(classes = PublishMsgEvent.class,
            condition = "#root.args[0].msgType == " + PatientMsgSendParamBO.MsgType.RECOMMEND)
    public void publishMsg4Recom(PublishMsgEvent publishMsgEvent) {
        LOGGER.debug("处方消息");

        PublishMsgData msgData = publishMsgEvent.getEventData();
        String msgContent = msgData.getDoctorName() + "医生根据您的症状描述建议您使用以下药品：\n\n" + msgData.getRecomMsg() +
                "\n处方当日有效，且只能购买一次，失效后请重新咨询医生\n----------\n" +
                webAuthorizeApiServiceImpl.getWebAuthorizeUrlSilent(
                        ConfigUtil.getString("wechat.redirect.common.url"),
                        PatientJumperEnum.RECOM_DETAIL.encodeWxParamStr(msgData.getRecomId().toString()),
                        "【查看处方】");
        BaseCustomParam customMsgParam = new TextMsgParam(msgData.getOpenId(), msgContent);
        String msgView = "【处方】";

        this.doPublish(msgData, customMsgParam, msgView, null);
    }

    /**
     * 病历消息
     *
     * @param publishMsgEvent
     */
    @Async
    @EventListener(classes = PublishMsgEvent.class,
            condition = "#root.args[0].msgType == " + PatientMsgSendParamBO.MsgType.MEDICALRECORD)
    public void publishMsg4MedicalRecord(PublishMsgEvent publishMsgEvent) {
        LOGGER.debug("病历消息");
        PublishMsgData msgData = publishMsgEvent.getEventData();
        if(msgData.getOnActive()){
            String msgContent = msgData.getDoctorName() + "医生根据您的症状，为您写了一份病历，点击就可以查看！\n----------\n" +
                    webAuthorizeApiServiceImpl.getWebAuthorizeUrlSilent(
                            ConfigUtil.getString("wechat.redirect.common.url"),
                            PatientJumperEnum.MEDICAL_RECORD_DETAIL.encodeWxParamStr(msgData.getMedicalRecordId()),
                            "【查看病历】");
            BaseCustomParam customMsgParam = new TextMsgParam(msgData.getOpenId(), msgContent);
            customMsgApiService.sendCustomMsg(customMsgParam);
            return;
        }
        MedicalSubscribe medicalSubscribe = MedicalSubscribe.builder().date(DateUtil.getCurrentFormatDate()).build();
        medicalSubscribe.setOpenId(msgData.getOpenId());
        medicalSubscribe.setTargetPage(webAuthorizeApiServiceImpl.getWebAuthorizeUrlSilent(
                ConfigUtil.getString("wechat.redirect.common.url"),
                PatientJumperEnum.MEDICAL_RECORD_DETAIL.encodeWxParamStr(msgData.getMedicalRecordId())));
        Integer errcode = subscribeNoticeService.notice(medicalSubscribe);
        if (errcode != 0) {
            MedicalRecordMsg medicalRecordMsg = MedicalRecordMsg.builder().doctorName(msgData.getDoctorFullName()).build();
            medicalRecordMsg.setOpenId(msgData.getOpenId());
            medicalRecordMsg.setTargetPage(webAuthorizeApiServiceImpl.getWebAuthorizeUrlSilent(
                    ConfigUtil.getString("wechat.redirect.common.url"),
                    PatientJumperEnum.MEDICAL_RECORD_DETAIL.encodeWxParamStr(msgData.getMedicalRecordId())));
            templateNoticeService.notice(medicalRecordMsg);
        }
    }

    /**
     * 付费成功消息
     *
     * @param publishMsgEvent
     */
    @Async
    @EventListener(classes = PublishMsgEvent.class,
            condition = "#root.args[0].msgType == " + PatientMsgSendParamBO.MsgType.PAIDCONSULT)
    public void publishMsg4PaidConsult(PublishMsgEvent publishMsgEvent) {
        LOGGER.debug("支付成功消息");
        PublishMsgData msgData = publishMsgEvent.getEventData();
        //支付成功，刷新客服消息
        RedisUtil.valueOps().setString(CommonConstant.CONSULT_PATIENT_ACTIVE + msgData.getOpenId(), msgData.getOpenId(), 48 * 60 * 60);
        //支付成功，切换当前咨询医生至该医生
        RedisUtil.hashOps().hset(CommonConstant.CONSULT_PATIENT_AIM, msgData.getPatientId().toString(), msgData.getDoctorId().toString());
        RedisUtil.hashOps().hset(CommonConstant.CONSULT_PATIENT_AIM_NAME, msgData.getPatientId().toString(), msgData.getDoctorName());
        customMsgApiService.sendSystemMsg(msgData.getOpenId(), msgData.getContent());
    }

    /**
     * 视频问诊消息
     * @param publishMsgEvent
     */
    @Async
    @EventListener(classes = PublishMsgEvent.class,
            condition = "#root.args[0].msgType == " + PatientMsgSendParamBO.MsgType.MINIPROGRAMPAGE)
    public void publishMsgMiniProgram(PublishMsgEvent publishMsgEvent) {
        PublishMsgData msgData = publishMsgEvent.getEventData();
        MsgPublishMpParamBO msgPublishMpParam = msgData.getMsgPublishMpParam();
        if (null == msgPublishMpParam) {
            LOGGER.error("推送视频问诊消息失败：{}", JSONUtil.toJsonStr(msgData));
            return;
        }
        if (msgData.getOnActive()) {
            customMsgApiService.sendMiniProgramMsg(msgData.getOpenId(),
                    msgPublishMpParam.getTitle(),
                    msgPublishMpParam.getAppId(),
                    msgPublishMpParam.getPagePath(),
                    msgPublishMpParam.getThumbMediaId());
            return;
        }
        ReminderSubscribe reminderSubscribe = ReminderSubscribe.builder().doctorName(msgData.getDoctorName())
                .patientName(msgData.getPatientName()).startTime(DateUtil.getCurrentFormatDateTime()).build();
        reminderSubscribe.setOpenId(msgData.getOpenId());
        reminderSubscribe.setMiniProgram(SubscribeMp.builder().appId(msgPublishMpParam.getAppId()).pagePath(msgPublishMpParam.getPagePath()).build());
        subscribeNoticeService.notice(reminderSubscribe);
    }

    //====================================================
    // 普通消息公共推送逻辑
    //====================================================
    private void doPublish(PublishMsgData msgData, BaseCustomParam customMsgParam, String msgView, String msgSimple) {
        //客服消息激活
        if (msgData.getOnActive()) {
            String endingMsg = "";
            String doctorInfo = webAuthorizeApiServiceImpl.getWebAuthorizeUrlSilent(ConfigUtil.getString("wechat.redirect.common.url"),
                    PatientJumperEnum.DOCTOR_DETAIL.encodeWxParamStr(msgData.getDoctorId().toString()), "点击这里可回复" + msgData.getDoctorName() + "医生");

            String aimDoctor = RedisUtil.hashOps().hget(CommonConstant.CONSULT_PATIENT_AIM, msgData.getPatientId().toString());
            String aimDoctorName = RedisUtil.hashOps().hget(CommonConstant.CONSULT_PATIENT_AIM_NAME, msgData.getPatientId().toString());
            Long aimDoctorId = StringUtils.isNumeric(aimDoctor) ? Long.valueOf(aimDoctor) : null;
            if (aimDoctorId == null) {
                endingMsg = "\n----------\n" + doctorInfo;
            } else if (!aimDoctorId.equals(msgData.getDoctorId())) {
                endingMsg = "\n----------\n您当前正咨询" + aimDoctorName + "医生，" + doctorInfo;
            }

            if (StringUtils.isNotBlank(msgSimple)) {
                customMsgApiService.sendSystemMsg(msgData.getOpenId(), msgSimple + endingMsg);
            }
            if (PatientMsgSendParamBO.MsgType.TEXT == msgData.getMsgType() || PatientMsgSendParamBO.MsgType.RECOMMEND == msgData.getMsgType()) {
                String msg = ((TextMsgParam) customMsgParam).getContent();
                ((TextMsgParam) customMsgParam).setContent(msg + endingMsg);
            }
            customMsgApiService.sendCustomMsg(customMsgParam);
            return;
        }

        // 非客服消息激活状态，订阅通知——>推送
        ConsultReplySubscribe consultReplySubscribe = ConsultReplySubscribe.builder().replier(msgData.getDoctorFullName()).reply(msgView).replyTime(DateUtil.getCurrentFormatDateTime()).build();
        consultReplySubscribe.setOpenId(msgData.getOpenId());
        consultReplySubscribe.setTargetPage(webAuthorizeApiServiceImpl.getWebAuthorizeUrlSilent(ConfigUtil.getString("wechat.redirect.common.url"),
                PatientMsgSendParamBO.MsgType.RECOMMEND == msgData.getMsgType() ?
                        PatientJumperEnum.RECOM_DETAIL.encodeWxParamStr(msgData.getRecomId().toString()) :
                        PatientJumperEnum.CHAT_HISTORY.encodeWxParamStr(msgData.getDoctorId().toString())));
        Integer errcode = subscribeNoticeService.notice(consultReplySubscribe);
        if (errcode != 0) {
            // 非客服消息激活状态，模板消息——>推送
            OutlineMsg outlineMsg = OutlineMsg.builder().doctorName(msgData.getDoctorFullName()).patientName(msgData.getPatientName()).consultMsg(msgView).build();
            outlineMsg.setOpenId(msgData.getOpenId());
            // 视频问诊，推送处方可能不存在会话历史，此处若为处方模板消息，直接跳转处方详情
            outlineMsg.setTargetPage(webAuthorizeApiServiceImpl.getWebAuthorizeUrlSilent(ConfigUtil.getString("wechat.redirect.common.url"),
                    PatientMsgSendParamBO.MsgType.RECOMMEND == msgData.getMsgType() ?
                            PatientJumperEnum.RECOM_DETAIL.encodeWxParamStr(msgData.getRecomId().toString()) :
                            PatientJumperEnum.CHAT_HISTORY.encodeWxParamStr(msgData.getDoctorId().toString())));
            templateNoticeService.notice(outlineMsg);
        }
    }
}
